/* eslint-disable @typescript-eslint/no-unused-vars */
import {
  ArgumentMetadata,
  BadRequestException,
  Injectable,
  Paramtype,
  ValidationPipe,
} from '@nestjs/common';
import { DTO_VALIDATION_OPTIONS } from './core/constants';
import { merge, isObject, omit } from 'lodash';

@Injectable()
export class AppPipe extends ValidationPipe {
  async transform(value: any, metadata: ArgumentMetadata): Promise<any> {
    console.log(value);
    const { type, metatype } = metadata;
    const dto = metatype as any;
    const options = Reflect.getMetadata(DTO_VALIDATION_OPTIONS, dto) || {};
    const originOptions = { ...this.validatorOptions };
    const orginTransform = { ...this.transformOptions };
    const { transformOptions, type: optionType, ...customOptions } = options;
    const requestType: Paramtype = optionType || 'body';
    if (requestType !== type) {
      return value;
    }
    if (transformOptions) {
      this.transformOptions = merge(
        this.transformOptions,
        transformOptions ?? {},
      );
    }
    this.validatorOptions = merge(this.validatorOptions, customOptions ?? {});
    const toValidate = isObject(value)
      ? Object.fromEntries(
          Object.entries(value as Record<string, any>).map(([key, v]) => {
            if (!isObject(v) || !('mimetype' in v)) return [key, v];
            return [key, omit(v, ['fields'])];
          }),
        )
      : value;
    try {
      let result = await super.transform(toValidate, metadata);
      if (typeof result.transform === 'function') {
        result = await result.transform(result);
        // eslint-disable-next-line no-unused-vars
        const { transform, ...data } = result;
        result = data;
      }
      this.validatorOptions = originOptions;
      this.transformOptions = orginTransform;
      return result;
    } catch (e) {
      // 重置验证选项
      this.validatorOptions = originOptions;
      // 重置transform选项
      this.transformOptions = orginTransform;
      if ('response' in e) throw new BadRequestException(e.response);
      throw new BadRequestException(e);
    }
  }
}
